/*
 * Copyright (c) 2015, the Dart project authors.
 *
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package vm.element

// This file is generated by the script: pkg/vm_service/tool/generate.dart in dart-lang/sdk.

import com.google.gson.JsonArray
import com.google.gson.JsonObject

/**
 * {@link Event} 是来自 VM 的异步通知。只有当客户端使用 streamListen RPC 订阅了事件流时才会传递此通知。
 */
open class Event(json: JsonObject) : Response(json) {

    /**
     * 已注册服务的别名。
     *
     * 为以下事件类型提供：
     *  - ServiceRegistered
     *
     * 可以返回 <code>null</code>。
     */
    fun getAlias(): String? {
        return getAsString("alias")
    }

    /**
     * 隔离体是否在 await、yield 或 yield* 语句处暂停？
     *
     * 为以下事件类型提供：
     *  - PauseBreakpoint
     *  - PauseInterrupted
     *
     * 可以返回 <code>null</code>。
     */
    fun getAtAsyncSuspension(): Boolean {
        return getAsBoolean("atAsyncSuspension")
    }

    /**
     * 已添加、删除或解析的断点。
     *
     * 为以下事件类型提供：
     *  - PauseBreakpoint
     *  - BreakpointAdded
     *  - BreakpointRemoved
     *  - BreakpointResolved
     *  - BreakpointUpdated
     *
     * 可以返回 <code>null</code>。
     */
    fun getBreakpoint(): Breakpoint? {
        val obj = json.get("breakpoint")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return Breakpoint(obj)
    }

    /**
     * 以 base64 字符串编码的字节数组。
     *
     * 为 WriteEvent 事件提供。
     *
     * 可以返回 <code>null</code>。
     */
    fun getBytes(): String? {
        return getAsString("bytes")
    }

    /**
     * 包含最近样本的 CPU 配置文件。
     *
     * 可以返回 <code>null</code>。
     */
    fun getCpuSamples(): CpuSamplesEvent? {
        val obj = json.get("cpuSamples")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return CpuSamplesEvent(obj)
    }

    /**
     * 与此事件关联的异常，如果这是 PauseException 事件。
     *
     * 可以返回 <code>null</code>。
     */
    fun getException(): InstanceRef? {
        val obj = json.get("exception")?.asJsonObject ?: return null
        return InstanceRef(obj)
    }

    /**
     * 扩展事件数据。
     *
     * 为 Extension 事件提供。
     *
     * 可以返回 <code>null</code>。
     */
    fun getExtensionData(): ExtensionData? {
        val obj = json.get("extensionData")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return ExtensionData(obj)
    }

    /**
     * 扩展事件类型。
     *
     * 为 Extension 事件提供。
     *
     * 可以返回 <code>null</code>。
     */
    fun getExtensionKind(): String? {
        return getAsString("extensionKind")
    }

    /**
     * 已添加扩展的 RPC 名称。
     *
     * 为 ServiceExtensionAdded 事件提供。
     *
     * 可以返回 <code>null</code>。
     */
    fun getExtensionRPC(): String? {
        return getAsString("extensionRPC")
    }

    /**
     * The name of the changed flag.
     *
     * This is provided for the event kinds:
     *  - VMFlagUpdate
     *
     * Can return <code>null</code>.
     */
    fun getFlag(): String? {
        return getAsString("flag")
    }

    /**
     * The garbage collection (GC) operation performed.
     *
     * This is provided for the event kinds:
     *  - GC
     *
     * Can return <code>null</code>.
     */
    fun getGcType(): String? {
        return getAsString("gcType")
    }

    /**
     * The argument passed to dart:developer.inspect.
     *
     * This is provided for the Inspect event.
     *
     * Can return <code>null</code>.
     */
    fun getInspectee(): InstanceRef? {
        val obj = json.get("inspectee")?.asJsonObject ?: return null
        return InstanceRef(obj)
    }

    /**
     * The isolate with which this event is associated.
     *
     * This is provided for all event kinds except for:
     *  - VMUpdate, VMFlagUpdate
     *
     * Can return <code>null</code>.
     */
    fun getIsolate(): IsolateRef? {
        val obj = json.get("isolate")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return IsolateRef(obj)
    }

    /**
     * What kind of event is this?
     */
    fun getKind(): EventKind {
        val value = json.get("kind")
        try {
            return if (value == null) EventKind.Unknown else EventKind.valueOf(value.asString)
        } catch (e: IllegalArgumentException) {
            return EventKind.Unknown
        }
    }

    /**
     * Specifies whether this event is the last of a group of events.
     *
     * This is provided for the event kinds:
     *  - HeapSnapshot
     *
     * Can return <code>null</code>.
     */
    fun getLast(): Boolean {
        return getAsBoolean("last")
    }

    /**
     * LogRecord data.
     *
     * This is provided for the Logging event.
     *
     * Can return <code>null</code>.
     */
    fun getLogRecord(): LogRecord? {
        val obj = json.get("logRecord")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return LogRecord(obj)
    }

    /**
     * The RPC method that should be used to invoke the service.
     *
     * This is provided for the event kinds:
     *  - ServiceRegistered
     *  - ServiceUnregistered
     *
     * Can return <code>null</code>.
     */
    fun getMethod(): String? {
        return getAsString("method")
    }

    /**
     * The new value of the changed flag.
     *
     * This is provided for the event kinds:
     *  - VMFlagUpdate
     *
     * Can return <code>null</code>.
     */
    fun getNewValue(): String? {
        return getAsString("newValue")
    }

    /**
     * The list of breakpoints at which we are currently paused for a PauseBreakpoint event.
     *
     * This list may be empty. For example, while single-stepping, the VM sends a PauseBreakpoint
     * event with no breakpoints.
     *
     * If there is more than one breakpoint set at the program position, then all of them will be
     * provided.
     *
     * This is provided for the event kinds:
     *  - PauseBreakpoint
     *
     * Can return <code>null</code>.
     */
    fun getPauseBreakpoints(): ElementList<Breakpoint>? {
        if (json.get("pauseBreakpoints") == null) return null

        return object : ElementList<Breakpoint>(json.get("pauseBreakpoints").asJsonArray) {
            override fun basicGet(array: JsonArray, index: Int): Breakpoint {
                return Breakpoint(array.get(index).asJsonObject)
            }
        }
    }

    /**
     * The previous UserTag label.
     *
     * Can return <code>null</code>.
     */
    fun getPreviousTag(): String? {
        return getAsString("previousTag")
    }

    /**
     * The service identifier.
     *
     * This is provided for the event kinds:
     *  - ServiceRegistered
     *  - ServiceUnregistered
     *
     * Can return <code>null</code>.
     */
    fun getService(): String? {
        return getAsString("service")
    }

    /**
     * The status (success or failure) related to the event. This is provided for the event kinds:
     *  - IsolateReloaded
     *
     * Can return <code>null</code>.
     */
    fun getStatus(): String? {
        return getAsString("status")
    }

    /**
     * An array of TimelineEvents
     *
     * This is provided for the TimelineEvents event.
     *
     * Can return <code>null</code>.
     */
    fun getTimelineEvents(): ElementList<TimelineEvent>? {
        if (json.get("timelineEvents") == null) return null

        return object : ElementList<TimelineEvent>(json.get("timelineEvents").asJsonArray) {
            override fun basicGet(array: JsonArray, index: Int): TimelineEvent {
                return TimelineEvent(array.get(index).asJsonObject)
            }
        }
    }

    /**
     * The timestamp (in milliseconds since the epoch) associated with this event. For some isolate
     * pause events, the timestamp is from when the isolate was paused. For other events, the
     * timestamp is from when the event was created.
     */
    fun getTimestamp(): Long {
        return if (json.get("timestamp") == null) -1 else json.get("timestamp").asLong
    }

    /**
     * The top stack frame associated with this event, if applicable.
     *
     * This is provided for the event kinds:
     *  - PauseBreakpoint
     *  - PauseInterrupted
     *  - PauseException
     *
     * For PauseInterrupted events, there will be no top frame if the isolate is idle (waiting in the
     * message loop).
     *
     * For the Resume event, the top frame is provided at all times except for the initial resume
     * event that is delivered when an isolate begins execution.
     *
     * Can return <code>null</code>.
     */
    fun getTopFrame(): Frame? {
        val obj = json.get("topFrame")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return Frame(obj)
    }

    /**
     * The new set of recorded timeline streams.
     *
     * This is provided for the TimelineStreamSubscriptionsUpdate event.
     *
     * Can return <code>null</code>.
     */
    fun getUpdatedStreams(): List<String>? {
        return if (json.get("updatedStreams") == null) null else getListString("updatedStreams")
    }

    /**
     * The current UserTag label.
     *
     * Can return <code>null</code>.
     */
    fun getUpdatedTag(): String? {
        return getAsString("updatedTag")
    }

    /**
     * The vm with which this event is associated.
     *
     * This is provided for the event kind:
     *  - VMUpdate, VMFlagUpdate
     *
     * Can return <code>null</code>.
     */
    fun getVm(): VMRef? {
        val obj = json.get("vm")?.asJsonObject ?: return null
        val type = json.get("type")?.asString
        if ("Instance" == type || "@Instance" == type) {
            val kind = json.get("kind")?.asString
            if ("Null" == kind) return null
        }
        return VMRef(obj)
    }
}
